﻿using AiMoBridge.Interface;
using AiMoWindows.CodeScripts.IO;
using AiMoWindows.Entrance.Connect;
using AiMoWindows.GHAiMo;
using AiMoWindows.Localization;
using AiMoWindows.MainActions;
using AiMoWindows.MainActions.Mode;
using AiMoWindows.Server;
using System.IO;
using System.Windows;

namespace AiMoWindows
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    partial class App : Application
    {
        public App()
        {
            //AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
        }
        private static PipeClient? CurrentPipe = null;

        /// <summary>
        /// 获取应用程序AiMo3d.exe的开始路径
        /// </summary>
        static string StartupPath { get; } = AppDomain.CurrentDomain.BaseDirectory;
        /// <summary>
        /// 当程序打开时运行
        /// 检测是否包含路径，打开A
        /// </summary>
        protected override void OnStartup(StartupEventArgs e)
        {
            string[] args = e.Args;

#if DEBUGWITHRHINO
#warning 现在是Debug Rhino Pipeline 模式
            args = new string[] { "AimoPipe_123456" };
#endif
#if DEBUGGH
#warning 现在是Debug GH Pipeline 模式
            args = new string[] { "AimoPipe_GH_123456" };
#endif


            ExecuterMode openMode = ExecuterMode.None;

            if (args.Length == 0)
            {
                // 直接从外部打开的
                if (OpenAiMoWindow(openMode, null))
                {
                    base.OnStartup(e);
                }
                else
                {
                    throw new ApplicationException("Interupt Startup: Cannot Open AiMo Window");
                }
                return;
            }
            string maybeAFile = args[0];
            if (CodeIO.IsValidAiMoScriptFilePath(maybeAFile) && File.Exists(maybeAFile))
            {
                // WIP 当已有AiMo打开时，让已经打开的AiMo打开文件。
                if (!OpenAiMoWindow(openMode, null, maybeAFile))
                {
                    throw new ApplicationException("Interupt Startup: Cannot Open AiMo Window");
                }
                base.OnStartup(e);
                return;
            }
            string serverPipeName = args[0];
            string ghScriptFilePath;
            if (serverPipeName.StartsWith("AimoPipe_GH_"))
            {
                openMode = ExecuterMode.Grasshopper;
                ghScriptFilePath = GHScriptIO.GetFileNameFromPipeName(serverPipeName);
                if (!File.Exists(ghScriptFilePath))
                {
                    ghScriptFilePath = "";
                    //throw new ApplicationException($"Interupt Startup: AiMo GH Open without existed passed gh file path: {ghScriptFilePath}");
                }
            }
            else
            {
                openMode = ExecuterMode.Rhino;
                ghScriptFilePath = "";
            }

            AppBridgeInfo appBridgeInfo;
            try
            {
                CurrentPipe = new PipeClient(serverPipeName);
                CurrentPipe.Init(out string currentRhinoVersion, out string[] rhinoAssemblyLocations);
                appBridgeInfo = new AppBridgeInfo(CurrentPipe, currentRhinoVersion, rhinoAssemblyLocations);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Cannot build connection to AiMo3D in AiMoRhino.\r\n   {ex.FormatException()}");

                throw new ApplicationException("Interupt Startup: Cannot build connection to AiMo3D");
            }
            if (!OpenAiMoWindow(openMode, appBridgeInfo, ghPassedFilePath: ghScriptFilePath))
            {
                throw new ApplicationException("Interupt Startup: Cannot Open AiMo Window");
            }

            base.OnStartup(e);
        }

        /// <summary>
        /// 通过这个函数，打开AiMo窗口
        /// 全局只会运行一次这个函数。
        /// </summary>
        static bool OpenAiMoWindow(ExecuterMode openMode, AppBridgeInfo? appBridgeInfo, string filePath = "", string ghPassedFilePath = "")
        {

            if (openMode == ExecuterMode.None)
            {
                Attentions.AttentionContent = Local.Get("If you open AiMo not through the \"AiMo\" command in Rhino, you can only compile DLLs but not run scripts within Rhino.");
            }

            IAppEntrance entrance = new Entrance.AiMoProgram(openMode, ghPassedFilePath);
            try
            {
                if (appBridgeInfo == null)
                {
                    //外部无Rhino打开的AiMo
                    if (!entrance.Init(StartupPath, out string error0))
                    {
                        MessageBox.Show($"Cannot init aimo app from {StartupPath}: " + error0);
                        return false;
                    }
                }
                else
                {
                    if (CurrentPipe == null)
                    {
                        MessageBox.Show($"Cannot init aimo app: pipe executor is null");
                        return false;
                    }
                    PipeExecutor executor = new PipeExecutor(CurrentPipe);
                    if (!entrance.Init(executor, appBridgeInfo, out string error1))
                    {
                        MessageBox.Show($"Cannot init aimo app {filePath}: " + error1);
                        return false;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Cannot init connection.\r\n    {ex.FormatException()}");
                return false;
            }
            if (!entrance.Start(filePath, true, out string error))
            {
                MessageBox.Show($"Cannot start aimo app {filePath}.\r\n    {error}");
                return false;
            }
            return true;
        }

        protected override void OnExit(ExitEventArgs e)
        {
            base.OnExit(e);
            CurrentPipe?.Dispose();
            Current.Shutdown();
        }
    }
}
